package me.magicall.test.socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.Socket;

public class MonitorClient {
	private final String host;
	private final int port;

	public MonitorClient(final String host, final int port) {
		super();
		this.host = host;
		this.port = port;
	}

	protected Object response(final InputStream inputStream) {
		// 注:关闭ObjectInputStream将关闭它包装的InputStream,而关闭这个从Socket中来的inputStream将关闭Socket!
		// 因此这个ObjectInputStream不能close!我靠
		try {
			final ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
			final Object obj = objectInputStream.readObject();
			return obj;
		} catch (final IOException e) {
			e.printStackTrace();
		} catch (final ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	public Object connect(final Serializable dto) throws Exception {
		Socket socket = null;
		try {
			socket = new Socket(host, port);
			final OutputStream outputStream = socket.getOutputStream();
			// 注:关闭ObjectOutputStream将关闭它包装的outputStream,而关闭这个从Socket中来的outputStream将关闭Socket!
			// 因此这个ObjectOutputStream不能close!我靠
			final ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
			objectOutputStream.writeObject(dto);
			objectOutputStream.flush();

			final InputStream inputStream = socket.getInputStream();
			// 注:关闭ObjectInputStream将关闭它包装的InputStream,而关闭这个从Socket中来的inputStream将关闭Socket!
			// 因此这个ObjectInputStream不能close!我靠
			try {
				final ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
				final Object obj = objectInputStream.readObject();
				if (obj instanceof Exception) {
					throw (Exception) obj;
				}
				return obj;
			} catch (final IOException e) {
				e.printStackTrace();
			} catch (final ClassNotFoundException e) {
				e.printStackTrace();
			}
			return null;
		} finally {
			if (socket != null) {
				try {
					socket.close();
				} catch (final IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void main(final String[] args) throws Exception {
		final int port = 8848;
		// 启动一个线程作为"服务器"
		final Monitor monitor = new Monitor(port) {
			@Override
			protected void checkOrder(final InputStream inputStream, final OutputStream outputStream) {
				// "服务器"做的事情就是把发送来的消息再发送回给客户端
				try {
					// 注:关闭ObjectInputStream将关闭它包装的InputStream,而关闭这个从Socket中来的inputStream将关闭Socket!因此这个不能关闭!我靠
					final ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
					final Object obj = objectInputStream.readObject();
					System.out.println("@@@@@@server:" + obj);
					final ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
					objectOutputStream.writeObject(obj);
					objectOutputStream.flush();
				} catch (final IOException e) {
					e.printStackTrace();
				} catch (final ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		};
		monitor.open();
		// 主线程作为"客户端",每秒请求一次"服务器",发送一个字符串给它
		final MonitorClient client = new MonitorClient("127.0.0.1", port);
		while (true) {
			try {
				Thread.sleep(1000);
			} catch (final InterruptedException e) {
				e.printStackTrace();
			}
			final Object returnFromServer = client.connect("haha");
			System.out.println("@@@@@@client:" + returnFromServer);
		}
	}
}
